package com.vf.editor.common.plugins.shiro;

import java.io.UnsupportedEncodingException;
import java.util.Base64;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.DefaultPasswordService;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.vf.editor.common.model.system.SysUser;

public class ShiroRealm extends AuthorizingRealm {
	
	protected final Log LOG = Log.getLog(getClass());
	
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken authcToken = (UsernamePasswordToken) token;
		String username = authcToken.getUsername();
		if (StrKit.isBlank(username)) {
			throw new UnknownAccountException("账号不可以为空!");
		}
		
		String password = String.valueOf(authcToken.getPassword());
		byte[] bytes = Base64.getDecoder().decode(username);
		byte[] bytes1 = Base64.getDecoder().decode(password);
	    try {
	    	username=new String(bytes, "UTF-8");
	    	password=new String(bytes1, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new UnknownAccountException("账号或密码错误!");
		}
		
		SysUser sysAccount = SysUser.dao.findUserByUsername(username);
		if (null == sysAccount) {
			throw new UnknownAccountException("用户名或密码错误!");
		} else {
			PasswordService svc = new DefaultPasswordService();
			try {
				if (svc.passwordsMatch(password, sysAccount.getPASSWORD())) {
					try {
						sysAccount.setLOGINTIMES(0);
						sysAccount.update();
					}catch (Exception e) {
					}
					return new SimpleAuthenticationInfo(
							new SimpleUser(sysAccount.getID(), sysAccount.getUSERNAME(), sysAccount.getNAME()),String.valueOf(authcToken.getPassword()), getName());
				} else {
					if(sysAccount.getLOGINTIMES()>=sysAccount.getERRORTIMES()) {
						throw new AuthenticationException("错误尝试次数过多，账户已锁定，请联系管理员解锁或24小时后再次尝试!");
					}else {
						try {
							sysAccount.setLOGINTIMES(sysAccount.getLOGINTIMES()+1);
							sysAccount.update();
						}catch (Exception e) {
						}
						throw new AuthenticationException("用户名或密码错误!");
					}
				}
			}catch (Exception e) {
				throw new UnknownAccountException("用户名或密码错误!");
			}
		}
	}

	/**
	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

		SimpleUser simpleUser = (SimpleUser) principals.fromRealm(getName()).iterator().next();
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		if (null == simpleUser) {
			return authorizationInfo;
		}
		return authorizationInfo;
	}

	/**
	 * 重写方法,清除当前用户的的 授权缓存
	 * @param principals
	 */
	@Override
	public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
		super.clearCachedAuthorizationInfo(principals);
	}

	/**
	 * 重写方法，清除当前用户的 认证缓存
	 * 
	 * @param principals
	 */
	@Override
	public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
		super.clearCachedAuthenticationInfo(principals);
	}

	@Override
	public void clearCache(PrincipalCollection principals) {
		super.clearCache(principals);
	}

	/**
	 * 自定义方法：清除所有 授权缓存
	 */
	public void clearAllCachedAuthorizationInfo() {
		getAuthorizationCache().clear();
	}

	/**
	 * 自定义方法：清除所有 认证缓存
	 */
	public void clearAllCachedAuthenticationInfo() {
		getAuthenticationCache().clear();
	}

	/**
	 * 自定义方法：清除所有的 认证缓存 和 授权缓存
	 */
	public void clearAllCache() {
		clearAllCachedAuthenticationInfo();
		clearAllCachedAuthorizationInfo();
	}

	public void clearCachedAuthorization() {
		clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
		clearCache(SecurityUtils.getSubject().getPrincipals());
	}

}
